package com.grass.cropTradingCenter.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
import com.grass.cropTradingCenter.common.OutputException;
import com.grass.cropTradingCenter.constant.Constants;
import com.grass.cropTradingCenter.mapper.*;
import com.grass.cropTradingCenter.pojo.dto.shop.RealAuthStateDto;
import com.grass.cropTradingCenter.pojo.dto.shop.ShopHomeData;
import com.grass.cropTradingCenter.pojo.dto.shop.ShopUser;
import com.grass.cropTradingCenter.pojo.entity.*;
import com.grass.cropTradingCenter.pojo.vo.shop.ShopAuthVo;
import com.grass.cropTradingCenter.pojo.vo.user.LoginVo;
import com.grass.cropTradingCenter.pojo.vo.user.RegisterVo;
import com.grass.cropTradingCenter.pojo.vo.user.SendUserLoginVo;
import com.grass.cropTradingCenter.service.EmailService;
import com.grass.cropTradingCenter.service.MiniShopUserService;
import com.grass.cropTradingCenter.service.ShopAuthService;
import com.grass.cropTradingCenter.utils.SafeUtils;
import com.grass.cropTradingCenter.utils.SecurityUtils;
import com.grass.cropTradingCenter.utils.TokenUtil;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author zipan
 * @description 针对表【mini_shop_user】的数据库操作Service实现
 * @createDate 2024-01-23 19:41:54
 */
@Service
public class MiniShopUserServiceImpl extends ServiceImpl<MiniShopUserMapper, MiniShopUser>
        implements MiniShopUserService {

    @Autowired
    EmailService emailService;

    @Autowired
    StringRedisTemplate redisTemplate;

    @Autowired
    RedissonClient redissonClient;

    @Autowired
    ShopAuthService shopAuthService;

    @Autowired
    MiniShopMapper miniShopMapper;

    @Autowired
    UserCommitMapper userCommitMapper;

    @Autowired
    UserOrderMapper userOrderMapper;

    @Autowired
    GoodsMapper goodsMapper;

    /**
     * 登录邮箱注册
     *
     * @param vo
     */
    @Override
    public void sendEmailLogin(SendUserLoginVo vo) {
        // 查看是否有该用户
        checkIsExistUser(vo);
        emailService.sendCode(vo.getEmail());
    }

    /**
     * 判断是否存在用户
     * @param vo
     */
    public void checkIsExistUser(SendUserLoginVo vo){
        LambdaQueryWrapper<MiniShopUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(MiniShopUser::getShopUserEmail, vo.getEmail());
        int count = this.count(wrapper);
        if (count <= 0) {
            throw new OutputException("请先注册");
        }
    }

    @Override
    public void sendEmailRegister(SendUserLoginVo vo) {
        // 查看是否有该用户
        LambdaQueryWrapper<MiniShopUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(MiniShopUser::getShopUserEmail, vo.getEmail());
        int count = this.count(wrapper);
        if (count > 0) {
            throw new OutputException("该账号已经存在");
        }

        emailService.sendCode(vo.getEmail());
    }


    @Override
    public String login(LoginVo vo) {
        MiniShopUser miniUser = null;

        if (!StringUtils.isBlank(vo.getIdCode())) {
            // 验证码登录
            emailService.checkIdCode(vo.getEmail(), vo.getIdCode());
        } else {
            // 账号密码登录
            LambdaQueryWrapper<MiniShopUser> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(MiniShopUser::getShopUserEmail, vo.getEmail())
                    .eq(MiniShopUser::getShopUserPassword, SafeUtils.getSafePassword(vo.getPassword()));
            int count = this.count(wrapper);
            if (count <= 0) throw new OutputException("账号密码错误");
        }

        // 查找用户
        LambdaQueryWrapper<MiniShopUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(MiniShopUser::getShopUserEmail, vo.getEmail());
        miniUser = this.getOne(wrapper);
        return TokenUtil.getToken(miniUser.getShopUserId(), "shop");
    }

    /**
     * 注册，返回token
     *
     * @param vo
     * @return
     */
    @Override
    public String register(RegisterVo vo) throws InterruptedException {
        // 密码不为空
        if (StringUtils.isBlank(vo.getPassword())) throw new OutputException("密码不能为空");
        if (!vo.getPassword().equals(vo.getCheckPassword())) throw new OutputException("两次密码不一致");
        String safePassword = SafeUtils.getSafePassword(vo.getPassword());

        emailService.checkIdCode(vo.getEmail(), vo.getIdCode());
        MiniShopUser miniShopUser = null;
        RLock lock = redissonClient.getLock("REGISTER#SHOP#" + vo.getEmail());
        boolean isLock = false;
        try {
            isLock = lock.tryLock(3, 3, TimeUnit.SECONDS);
            if (isLock) {
                LambdaQueryWrapper<MiniShopUser> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(MiniShopUser::getShopUserEmail, vo.getEmail());
                int count = this.count(queryWrapper);
                if (count >= 1) throw new OutputException("账户已存在");
                // 添加用户信息
                miniShopUser = new MiniShopUser();
                miniShopUser.setShopUserEmail(vo.getEmail());
                miniShopUser.setShopUserNickname(vo.getNickName());
                miniShopUser.setShopUserAvatar("https://grassmall.oss-cn-beijing.aliyuncs.com/3ea6beec64369c2642b92c6726f1e.png");

                miniShopUser.setShopUserPassword(safePassword);
                this.save(miniShopUser);
            } else {
                throw new OutputException("网络繁忙，请重试");
            }
        } finally {
            if (lock.isLocked()) lock.unlock();
        }
        if (miniShopUser != null)
            return TokenUtil.getToken(miniShopUser.getShopUserId(), "shop");
        else throw new OutputException("网络繁忙，请重试");
    }

    @Override
    public String findPassword(RegisterVo vo) throws InterruptedException {
        // 密码不为空
        if (StringUtils.isBlank(vo.getPassword())) throw new OutputException("密码不能为空");
        if (!vo.getPassword().equals(vo.getCheckPassword())) throw new OutputException("两次密码不一致");
        String safePassword = SafeUtils.getSafePassword(vo.getPassword());

        emailService.checkIdCode(vo.getEmail(), vo.getIdCode());
        MiniShopUser miniShopUser = null;
        RLock lock = redissonClient.getLock("REGISTER#SHOP#" + vo.getEmail());
        boolean isLock = false;
        try {
            isLock = lock.tryLock(3, 3, TimeUnit.SECONDS);
            if (isLock) {
                LambdaQueryWrapper<MiniShopUser> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(MiniShopUser::getShopUserEmail, vo.getEmail());
                miniShopUser = this.getOne(queryWrapper);
                if (miniShopUser == null) throw new OutputException("账户不存在");
                miniShopUser.setShopUserPassword(safePassword);
                this.updateById(miniShopUser);
            } else {
                throw new OutputException("网络繁忙，请重试");
            }
        } finally {
            if (lock.isLocked()) lock.unlock();
        }
        if (miniShopUser != null)
            return TokenUtil.getToken(miniShopUser.getShopUserId(), "shop");
        else throw new OutputException("网络繁忙，请重试");
    }

    @Override
    public ShopUser getUserInfo() {
        int userId = SecurityUtils.getShopUserId();
        return getUserInfo(userId);
    }

    @Override
    public ShopUser getUserInfo(int userId) {
        // 先在缓存中取
        String redisKey = getShopUserRedisKey(userId);
        Gson gson = new Gson();
        String json = redisTemplate.opsForValue().get(redisKey);
//        if(StringUtils.isBlank(json)){
            MiniShopUser miniShopUser = this.getById(userId);
            ShopUser shopUser = new ShopUser();
            BeanUtils.copyProperties(miniShopUser, shopUser);
            // 密码脱敏
            shopUser.setShopUserPassword("");
            redisTemplate.opsForValue().set(redisKey, gson.toJson(shopUser), 1, TimeUnit.DAYS);
            return shopUser;
//        }
//        return gson.fromJson(json, ShopUser.class);
    }

    /**
     * 是否实名认证
     * @return
     */
    @Override
    public RealAuthStateDto realAuthState() {
        int shopUserId = SecurityUtils.getShopUserId();
        LambdaQueryWrapper<ShopAuth> queryWrapper = new LambdaQueryWrapper<>();
        // 该用户并且审核通过
        queryWrapper.eq(ShopAuth::getShopUserId, shopUserId);
        ShopAuth shopAuth = shopAuthService.getOne(queryWrapper);
        RealAuthStateDto res = new RealAuthStateDto();
        if(shopAuth == null) res.setState(0);
        else if(shopAuth.getCheckFlag() == 1) res.setState(1);
        else res.setState(2);

        MiniShopUser shopUser = this.getById(shopUserId);

        if(shopUser.getShopNum() >= 1) res.setShopState(1);
        else res.setShopState(0);

        return res;
    }

    @Override
    public void realAuth(ShopAuthVo vo) {
        int shopUserId = SecurityUtils.getShopUserId();
        LambdaQueryWrapper<ShopAuth> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShopAuth::getShopUserId, shopUserId);
        ShopAuth shopAuth = shopAuthService.getOne(queryWrapper);
        // 如果已经存在，则覆盖之前的信息
        if(shopAuth != null){
               shopAuth.setCreateTime(new Date());
               shopAuth.setIdCard(vo.getIdCard());
               shopAuth.setCheckFlag(0);
               shopAuth.setRealName(vo.getRealName());
               shopAuth.setIdCardBack(vo.getIdCardBack());
               shopAuth.setIdCardFront(vo.getIdCardFront());
               shopAuth.setPhone(vo.getPhone());
               shopAuth.setRemark("无");
               shopAuthService.updateById(shopAuth);
        }else {
            shopAuth = new ShopAuth();
            BeanUtils.copyProperties(vo, shopAuth);
            shopAuth.setShopUserId(shopUserId);
            shopAuth.setCheckFlag(0);
            shopAuthService.save(shopAuth);
        }
    }

    @Override
    public ShopAuth getRealAuth() {
        int shopUserId = SecurityUtils.getShopUserId();
        LambdaQueryWrapper<ShopAuth> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShopAuth::getShopUserId, shopUserId);
        ShopAuth shopAuth = shopAuthService.getOne(queryWrapper);
        if (shopAuth == null) throw new OutputException("你还没有提交实名认证信息");
        return shopAuth;
    }

    @Override
    public ShopHomeData homeData() {
        ShopHomeData res = new ShopHomeData();
        Integer shopId = getShopId();
        if (shopId == 0) {
            return res;
        }
        res.setBadNum(getBadNum());
        res.setAllCommit(getAllCommit());
        res.setCommonNum(getCommonNum());
        res.setGoodNum(getGoodNum());
        res.setRefundOrder(getRefundOrder());
        res.setSuccessOrder(getSuccessOrderNum());
        return res;
    }

    @Override
    public MiniShopUser userDetail() {
        MiniShopUser res = this.getById(SecurityUtils.getShopUserId());

        LambdaQueryWrapper<MiniShop> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MiniShop::getShopUserId, res.getShopUserId());
        List<MiniShop> shops = miniShopMapper.selectList(queryWrapper);
        if (shops.isEmpty()) {
            MiniShop shop = new MiniShop();
            shop.setGoodsNum(0);
            shop.setShopName("无");
            shop.setStartNum(0);
            shop.setGoodEvaluateNum(0);
            shop.setBadEvaluateNum(0);
            shop.setGeneralEvaluateNum(0);
            res.setMiniShop(shop);
            return res;
        }
        res.setMiniShop(shops.get(0));

        LambdaQueryWrapper<Goods> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Goods::getShopId, shops.get(0).getShopId())
                .eq(Goods::getSellFlag, 1)
                .eq(Goods::getCheckFlag, 1)
                .eq(Goods::getDelFlag, 0);
        res.getMiniShop().setGoodsNum(goodsMapper.selectCount(wrapper));
        return res;
    }

    @Override
    public void updateShopUser(MiniShopUser vo) {
        this.updateById(vo);
    }

    private Integer getSuccessOrderNum() {
        LambdaQueryWrapper<UserOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserOrder::getShopId, getShopId())
                .eq(UserOrder::getDelFlag, 0)
                .and(e -> {
                    e.or().eq(UserOrder::getOrderType, 4)
                            .or().eq(UserOrder::getOrderType, 5);
                });
        return userOrderMapper.selectCount(queryWrapper);
    }

    private Integer getRefundOrder() {
        LambdaQueryWrapper<UserOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserOrder::getShopId, getShopId())
                .eq(UserOrder::getDelFlag, 0)
                .and(e -> {
                    e.or().eq(UserOrder::getOrderType, 10)
                            .or().eq(UserOrder::getOrderType, 12);
                });
        return userOrderMapper.selectCount(queryWrapper);
    }

    private Integer getGoodNum() {
        LambdaQueryWrapper<UserCommit> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserCommit::getShopId, getShopId())
                .eq(UserCommit::getCommitType, 1)
                .eq(UserCommit::getCommitRate, 3);
        return userCommitMapper.selectCount(queryWrapper);
    }

    private Integer getCommonNum() {
        LambdaQueryWrapper<UserCommit> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserCommit::getShopId, getShopId())
                .eq(UserCommit::getCommitType, 1)
                .eq(UserCommit::getCommitRate, 2);
        return userCommitMapper.selectCount(queryWrapper);
    }

    private Integer getAllCommit() {
        LambdaQueryWrapper<UserCommit> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserCommit::getShopId, getShopId())
                .eq(UserCommit::getCommitType, 1);
        return userCommitMapper.selectCount(queryWrapper);
    }

    private Integer getBadNum() {
        LambdaQueryWrapper<UserCommit> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserCommit::getShopId, getShopId())
                .eq(UserCommit::getCommitType, 1)
                .eq(UserCommit::getCommitRate, 1);
        return userCommitMapper.selectCount(queryWrapper);
    }

    private Integer getShopId() {
        int userId = SecurityUtils.getShopUserId();
        LambdaQueryWrapper<MiniShop> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MiniShop::getShopUserId, userId);
        List<MiniShop> list = miniShopMapper.selectList(queryWrapper);
        if (list.isEmpty()) return 0;
        return list.get(0).getShopId();
    }

    String getShopUserRedisKey(int userId) {
        return Constants.REDIS_KEY_SHOP_USER + userId;
    }


}




